#include "client.h"
#define MAX_SIZE (25000*4096)

int recvn(int sockfd, void *buf, int length){
    char *pbuf = (char *)buf;
    int cursize = 0;
    while(cursize < length){
        ssize_t sret = recv(sockfd,pbuf + cursize,length - cursize,0);
        cursize += sret;
        if(sret == 0){
            break;
        }
    }
    return 0;
}

//正式接收时使用小火车：buf = train.data，*flag = &train.flag
int recvFile(int sockfd,char* buf,int *flag){
    train_t train ;
    recvn(sockfd,&train.flag,sizeof(train.flag));
    recvn(sockfd,&train.length,sizeof(train.length));
    recvn(sockfd,train.data,train.length);
    // 收名字
    char filename[4096] = {0};
    memcpy(filename,train.data,train.length);
    printf("filename = %s\n",filename);
    memcpy(filename,buf,strlen(buf));
    /* // 断点重传: 先不考虑文件路径打不开的问题 */
    /* int filefd=open(filename,O_RDWR|O_CREAT|O_TRUNC,0666); */
    /* if(filefd == -1){ */
    /*     printf("打开文件失败!\n"); */
    /*     return -1; */                
    /* } */
    // 收文件长度
    off_t filesize;//定义变量存储文件总大小
    recvn(sockfd,&train.flag,sizeof(train.flag));
    recvn(sockfd,&train.length,sizeof(train.length));
    recvn(sockfd,train.data,train.length);
    memcpy(&filesize,train.data,sizeof(off_t));//将接收到的文件大小数据转换为off_t类型
    printf("filesize = %ld\n",filesize);

    //-----------断点重传部分1-----------------------
    off_t offset = 0;
    int filefd=-1;
    int bpfilefd=-1;
    // .bp文件的名字，bp文件中现在只存已经传输的数据长度
    char bpfileName[1024]={0};
    strncpy(bpfileName,filename,strlen(filename)+1);
    strncat(bpfileName,".bp",4);
    // 找本地是否有同名文件
    int ret = access(filename,F_OK); 
    // 没有同名文件，正常传输，创建空文件，空.bp文件
    if (ret !=0){
        filefd=open(filename,O_RDWR|O_CREAT|O_TRUNC,0666);
        bpfilefd=open(bpfileName,O_RDWR|O_CREAT|O_TRUNC,0666);
        offset=0;
    }else{
        // 如果有同名文件检查文件长度是否相同
        filefd=open(filename,O_RDWR);
        struct stat statbuf;                              
        fstat(filefd,&statbuf);
        off_t localFilesize=statbuf.st_size;
        printf("本地同名文件的尺寸size = %ld\n",localFilesize);
        // 如果相同，不传
        if(localFilesize==filesize){
            printf("相同，不传\n");
            offset = filesize;
            filefd=open(filename,O_RDWR);
        }else{
            // 如果不同，找有没有.bp文件
            int ret = access(bpfileName,F_OK); 
            // 如果没有，offset = 0，重传，创建空文件，空.bp文件
            if(ret!=0){
                printf("没bp重传\n");
                offset = 0;
                filefd=open(filename,O_RDWR|O_CREAT|O_TRUNC,0666);
                bpfilefd=open(bpfileName,O_RDWR|O_CREAT|O_TRUNC,0666);
                usleep(1000);// 测试用
            }else{
                printf("有bp，从断点传\n");
                // 如果有，读取.bp文件，offset 修改 
                bpfilefd = open(bpfileName,O_RDWR);
                int readRet = read(bpfilefd,&offset,sizeof(off_t));
                ERROR_CHECK(readRet,-1,"client/recvFile/read bpfile");                
                lseek(bpfilefd,0,SEEK_SET);
                filefd=open(filename,O_RDWR);
                printf("断点位置%ld\n",offset);
            }
        }
    }

    //发送offset
    send(sockfd,&offset,sizeof(off_t),MSG_NOSIGNAL);
    lseek(filefd,offset,SEEK_SET);
    //----------------------------------

    while(1){//循环接收文件数据块并写入文件
        bzero(train.data,sizeof(train.data));
        recvn(sockfd,&train.flag,sizeof(train.flag));
        recvn(sockfd,&train.length,sizeof(train.length));
        if(train.length!=4096){
            printf("train.length = %d\n",train.length);
        }
        recvn(sockfd,train.data,train.length);
        if(train.length==0){
            break;
        }
        write(filefd,train.data,train.length);//将数据块写入文件
//----------------断点重传部分2--------------------------------------
        offset+=train.length;
        write(bpfilefd,&offset,sizeof(offset));
        // 重置bp读写指针
        lseek(bpfilefd,0,SEEK_SET);
        /* usleep(1000);// 测试用 */ 
    }
    if(remove(bpfileName) != 0){  // 删除指定文件名对应的绝对路径
        perror("delete .bp file");
    }
    close(bpfilefd);
    //------------------------------------------------------
    close(filefd);
    return 0;
}

